package com.example.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.common.R;
import com.example.domain.Movie;
import com.example.domain.Rating;
import com.example.domain.model.MovieDTO;
import com.example.mahout.RecommendationEngine;
import com.example.mapper.MovieMapper;
import com.example.service.RatingService;
import com.example.shiro.AccountProfile;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Api(tags = "推荐")
@RestController
@RequestMapping("/recommend")
public class RecommendationController {

    @Autowired
    private RecommendationEngine recommendationEngine;

    @Autowired
    private RatingService ratingService;

    @Autowired
    private MovieMapper movieMapper;

    @GetMapping
    public R<List<MovieDTO>> recommend() throws IOException, TasteException {
        //获取当前用户信息
        AccountProfile account = (AccountProfile) SecurityUtils.getSubject().getPrincipal();

        Long userId = Long.valueOf(account.getId());
        // 获取所有用户的评分数据
        List<Rating> ratings = ratingService.getAll();
        // 将评分数据转换为Apache Mahout推荐引擎可以使用的DataModel
        DataModel dataModel = convertToDataModel(ratings);
        // 使用推荐引擎为当前用户推荐5部电影
        List<RecommendedItem> recommend = recommendationEngine.recommend(dataModel, userId, 5);
        List<String> itemId = new ArrayList<>();
        for (RecommendedItem recommendedItem : recommend) {
            itemId.add(String.valueOf(recommendedItem.getItemID()));
        }
        if (!itemId.isEmpty()){
            List<MovieDTO> movies = movieMapper.selectRecommendiation(new LambdaQueryWrapper<Movie>().in(Movie::getId, itemId));
            return R.success(movies);
        }
        // 如果推荐电影ID列表为空，则返回推荐失败的消息
        return R.error("推荐失败");
    }

    public DataModel convertToDataModel(List<Rating> ratings) throws IOException {
        Path tempFile = Files.createTempFile("ratings", ".csv");
        try (BufferedWriter writer = Files.newBufferedWriter(tempFile, StandardOpenOption.WRITE)) {
            for (Rating rating : ratings) {
                writer.write(String.format("%s,%s,%f%n", rating.getUserId(), rating.getMovieId(), rating.getScore()));
            }
        }
        return new FileDataModel(tempFile.toFile());
    }

}
